<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>知识图谱 - 麻醉知识图谱 - 管理员</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <!--    导入bootstrap js文件-->
    <script src="https://cdn.staticfile.net/twitter-bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
    <style>
        html {
            height: 100%;
        }

        body {
            font-family: 'Noto Sans SC', Arial, sans-serif;
            height: 100%;
            background-color: #f8f9fa;
            margin: 0;
            padding: 0;
            overflow-x: hidden;
        }

        .navbar-custom {
            background-color: #2E3B4E;
            padding: 1rem 2rem;
        }

        .navbar-custom .navbar-nav .nav-link {
            color: white;
            font-size: 1.1rem;
            margin-right: 1rem;
        }

        .navbar-custom .navbar-nav .nav-link:hover {
            background-color: #1F2A3A;
            border-radius: 5px;
        }

        #container {
            display: flex;
            width: auto;
            /*height: 30%;*/
            /*width: 100%;*/
            flex-direction: column;
            align-items: center;
            animation: fadeIn 2s;
            padding-top: 8rem;
        }

        #search-container {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 40px;
        }

        input[type="text"] {
            width: 300px;
            padding: 10px;
            margin-right: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            transition: border-color 0.3s;
        }

        input[type="text"]:focus {
            border-color: #2E3B4E;
        }

        button {
            padding: 10px 20px;
            background-color: #2E3B4E;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s;
            margin: 5px;
        }

        button:hover {
            background-color: #1F2A3A;
        }

        #legend {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 20px;
        }

        .legend-item {
            display: flex;
            align-items: center;
            margin: 0 10px;
            cursor: pointer;
        }

        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 50%;
            margin-right: 5px;
        }

        #add-container {
            margin-bottom: 30px;
        }

        #graph-container {
            width: 98%;
            /*height: 100%;*/
            position: relative;
            padding: 20px;
            background: white;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            animation: slideInUp 2s;
            /*margin-bottom: 10rem;*/
            margin-top: 30px;
        }

        #node-info {
            position: absolute;
            top: 200px;
            right: 10px;
            width: 400px;
            padding: 15px;
            background: white;
            border: 1px solid #ccc;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
            display: none;
            font-family: 'Arial', sans-serif;
            font-size: 16px;
            color: #333;
            max-height: 70vh;
            /* 当内容超出时，整个面板会出现滚动条 */
        }

        .controls {
            position: absolute;
            top: 10px;
            right: 10px;
            display: flex;
            gap: 5px;
            z-index: 999;
        }

        .control-btn {
            width: 30px;
            height: 30px;
            font-size: 18px;
            cursor: pointer;
            border: none;
            background-color: #f0f0f0;
            border-radius: 50%;
        }

        .control-btn:hover {
            background-color: #e0e0e0;
        }

        #description-container {
            max-height: 30%;
            /* 设置简介部分占面板的30%最大高度 */
            overflow-y: auto;
            /* 当简介内容超出最大高度时，显示滚动条 */
        }

        #node-description {
            display: block;
            max-height: 150px;
            /* 简介的最大高度 */
            overflow-y: auto;
            /* 当简介内容超出高度时，显示滚动条 */
        }

        #node-info h3 {
            margin-top: 0;
            font-size: 20px;
            color: #2E3B4E;
            text-align: center;
            position: relative;
        }

        #node-info h3::after {
            content: '';
            display: block;
            width: 100px;
            height: 3px;
            background: black;
            margin: 10px auto 10px;
        }

        #node-info .info-item:nth-child(even) {
            background-color: #F5F5F5;
        }

        .info-item {
            margin-bottom: 10px;
        }

        #node-info .info-item {
            padding: 5px;
            background-color: white;
        }

        #node-info button {
            background-color: #1F2A3A;
            color: white;
            border: none;
            padding: 5px 20px;
            margin-top: 20px;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s;
            width: 100%;
        }

        #node-info button:hover {
            background-color: #444444;
        }

        #graph {
            width: 100%;
            height: 800px;
            border-radius: 4px;
            background: white;
        }

        .expand-icon {
            position: absolute;
            background-color: #2E3B4E;
            color: white;
            padding: 5px;
            border-radius: 50%;
            cursor: pointer;
            display: none;
        }

        @keyframes fadeIn {
            from {
                opacity: 0;
            }

            to {
                opacity: 1;
            }
        }

        @keyframes slideInUp {
            from {
                transform: translateY(100%);
            }

            to {
                transform: translateY(0);
            }
        }

        #edit-node-types div {
            padding: 5px 10px;
            background-color: #f0f0f0;
            border-radius: 10px;
            display: inline-block;
        }

        #edit-node-types div button {
            margin-left: 10px;
        }


        #nodeForm {
            max-width: 500px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f8f9fa;
            border: 1px solid #ced4da;
            border-radius: 5px;
        }

        .form-group {
            margin-bottom: 15px;
        }

        label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
        }

        .form-input,
        .form-select {
            width: 100%;
            padding: 8px;
            border: 1px solid #ced4da;
            border-radius: 4px;
            box-sizing: border-box;
        }

        .form-button {
            width: 100%;
            padding: 10px;
            background-color: #2E3B4E;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s;
        }

        .form-button:hover {
            background-color: #2E3B4E;
        }

        .modal-header {
            float: left;
        }

        .nav-button {
            background-color: #2E3B4E;
            color: white;
            font-size: 1.1rem;
            margin-right: 1rem;
            border: none;
            padding: 8px;
        }

        .nav-button:hover {
            background-color: #1F2A3A;
            border-radius: 5px;
        }
    </style>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css" rel="stylesheet" type="text/css" />
</head>

<body>
    <nav class="navbar navbar-expand-lg navbar-custom fixed-top">
        <div class="container-fluid">
            <a class="navbar-brand" href="/page">麻醉知识图谱</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
                aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="AI" href="/AI">AI助手</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="page" href="/page">主页</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">知识图谱</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#" onclick="checkLoginAndRedirect('/profile')">个人中心</a>
                    </li>
                    <li class="nav-item">
                        <button id="logoutButton" class="nav-button" onclick="logout()">注销</button>
                    </li>
                </ul>
            </div>
        </div>
    </nav>

    <div id="container">
        <div id="search-container">
            <input type="text" id="name" placeholder="请输入实体名称...">
            <button onclick="queryGraph()">查询</button>
            <button onclick="showExamplePatients(document.getElementById('name').value)">查看相关病历</button>
        </div>

        <button id="addButton" class="btn-custom" data-bs-toggle="modal" data-bs-target="#loginModal">新增节点
        </button>

        <div class="modal fade" id="loginModal" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="loginModalLabel">新增节点</h5>
                        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                    </div>
                    <div class="modal-body">
                        <form id="nodeForm">
                            <div class="form-group">
                                <label for="label">标签:</label>
                                <select id="label" name="label" class="form-select">
                                    <option value="1级风险因素">1级风险因素</option>
                                    <option value="2级风险因素">2级风险因素</option>
                                    <option value="体格检查">体格检查</option>
                                    <option value="基本信息 ">基本信息 </option>
                                    <option value="实验室检查">实验室检查</option>
                                    <option value="既往史">既往史</option>
                                    <option value="检查结果">检查结果</option>
                                    <option value="治疗">治疗</option>
                                    <option value="现病史">现病史</option>
                                    <!-- <option value="1级风险因素">1级风险因素</option>
                                    <option value="2级风险因素">2级风险因素</option> -->
                                    <!--                                <option value="疾病">疾病</option>-->
                                    <!--                                <option value="第三层级">第三层级</option>-->
                                    <!--                                <option value="第四层级">第四层级</option>-->
                                    <!--                                <option value="第五层级">第五层级</option>-->
                                    <!--                                <option value="吸烟情况">吸烟情况</option>-->
                                    <!--                                <option value="家族史">家族史</option>-->
                                    <!--                                <option value="手麻实施主手术">手麻实施主手术</option>-->
                                    <!--                                <option value="手麻实施从手术">手麻实施从手术</option>-->
                                    <!--                                <option value="既往史">既往史</option>-->
                                    <!--                                <option value="术前诊断">术前诊断</option>-->
                                    <!--                                <option value="术后诊断">术后诊断</option>-->
                                    <!--                                <option value="超声诊断意见">超声诊断意见</option>-->
                                    <!--                                <option value="饮酒情况">饮酒情况</option>-->
                                    <!--                                <option value="首页出院主要诊断">首页出院主要诊断</option>-->
                                    <!--                                <option value="首页出院其他诊断">首页出院其他诊断</option>-->
                                    <!--                                <option value="电脑多导联心电图">电脑多导联心电图</option>-->
                                </select>
                            </div>

                            <div class="form-group">
                                <label for="name1">名称:</label>
                                <input type="text" id="name1" name="name1" class="form-input" required>
                            </div>

                            <div class="form-group">
                                <label for="description">描述 (选填):</label>
                                <input type="text" id="description" name="description" class="form-input">
                            </div>

                            <div class="form-group">
                                <label for="targetName">目标节点名称:</label>
                                <input type="text" id="targetName" name="targetName" class="form-input"
                                    oninput="searchNodes()" required>
                            </div>

                            <div id="searchResults"></div>

                            <div class="form-group">
                                <label for="relationshipType">关系类型:</label>
                                <input type="text" id="relationshipType" name="relationshipType" class="form-input"
                                    required>
                            </div>

                            <div class="form-group">
                                <label for="relationshipDirection">关系方向:</label>
                                <select id="relationshipDirection" name="relationshipDirection" class="form-select"
                                    required>
                                    <option value="from_new_to_target">从新增到目标</option>
                                    <option value="from_target_to_new">从目标到新增</option>
                                </select>
                            </div>

                            <button type="submit" class="form-button">提交</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="graph-container">
        <div id="legend"></div>
        <div id="graph"></div>
        <div id="expand-icon" class="expand-icon">+</div>
        <div id="node-info">
            <div class="controls">
                <button class="control-btn" onclick="decreaseScale()">-</button>
                <button class="control-btn" onclick="increaseScale()">+</button>
            </div>
            <h3>节点信息</h3>
            <div class="info-item"><strong>编号:</strong> <span id="node-id"></span></div>
            <div class="info-item"><strong>名称:</strong> <span id="node-name"></span></div>
            <div class="info-item"><strong>类别:</strong> <span id="node-group"></span></div>
            <!-- 简介部分，设置滚动条，当内容过多时会出现 -->
            <div class="info-item" id="description-container">
                <strong>简介:</strong>
                <span id="node-description"></span>
            </div>
            <button onclick="showEditModal()">修改节点</button>
            <button onclick="showExamplePatients()">显示示例病人</button>
            <button onclick="toggleNodeInfo()">隐藏</button>
            <button onclick="delNodeInfo()" style="background-color: darkred; color: white;">删除节点</button>
        </div>

    </div>

    <div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg"> <!-- 使用larger modal -->
            <div class="modal-content" style="width: 900px;"> <!-- 控制整个弹出框的宽度 -->
                <div class="modal-header">
                    <h5 class="modal-title" id="editModalLabel">修改节点信息</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body" style="display: flex; flex-direction: column;">
                    <form id="editNodeForm" style="display: grid; grid-template-columns: 2fr 3fr 3fr; gap: 20px;">

                        <!-- 第一部分: 名称 -->
                        <div class="p-3"
                            style="border: 1px solid #e0e0e0; border-radius: 10px; display: flex; flex-direction: column;">
                            <h5 class="mb-3" style="color: #007bff; font-size: 1.2em;">节点名称</h5>
                            <div class="mb-3" style="flex-grow: 1;">
                                <label for="edit-node-name" class="form-label">名称</label>
                                <input type="text" class="form-control" id="edit-node-name" style="font-size: 0.9em;"
                                    required>
                            </div>
                        </div>

                        <!-- 第二部分: 简介 -->
                        <div class="p-3"
                            style="width: 209%; border: 1px solid #e0e0e0; border-radius: 10px; display: flex; flex-direction: column;">
                            <h5 class="mb-3" style="color: #007bff; font-size: 1.2em;">节点简介</h5>
                            <div class="mb-3" style="flex-grow: 1;">
                                <label for="edit-node-description" class="form-label">简介</label>
                                <textarea class="form-control" id="edit-node-description" rows="3"
                                    style="font-size: 0.9em;" required></textarea>
                            </div>
                        </div>

                        <!-- 第三部分: 修改类别 -->
                        <div class="p-3"
                            style="border: 1px solid #e0e0e0; border-radius: 10px; grid-column: span 3; display: flex; flex-direction: column;">
                            <h5 class="mb-3" style="color: #007bff; font-size: 1.2em;">修改类别</h5>
                            <label for="edit-node-types" class="form-label">已有类别</label>
                            <div id="edit-node-types"
                                style="display: flex; flex-wrap: wrap; gap: 10px; font-size: 0.9em;">
                                <!-- 类别部分会动态生成 -->
                            </div>
                            <div class="mt-3 d-flex align-items-center">
                                <div id="add-type-container" class="flex-grow-1"
                                    style="border: 1px dashed #007bff; border-radius: 10px; padding: 10px; display: flex; align-items: center;">
                                    <select class="form-control" id="new-type-select"
                                        style="border: none; outline: none; font-size: 0.9em;">
                                        <option value="">选择类别</option>
                                        <option value="1级风险因素">1级风险因素</option>
                                        <option value="2级风险因素">2级风险因素</option>
                                        <option value="体格检查">体格检查</option>
                                        <option value="基本信息">基本信息</option>
                                        <option value="实验室检查">实验室检查</option>
                                        <option value="既往史">既往史</option>
                                        <option value="检查结果">检查结果</option>
                                        <option value="治疗">治疗</option>
                                        <option value="现病史">现病史</option>
                                    </select>
                                </div>
                                <button type="button" onclick="addNodeType()" class="btn btn-outline-secondary ms-2"
                                    style="font-size: 0.9em;">添加</button>
                            </div>
                        </div>

                        <!-- 第四部分: 修改关系 -->
                        <div id="relationship-container" class="p-3"
                            style="border: 1px solid #e0e0e0; border-radius: 10px; grid-column: span 3; display: flex; flex-direction: column;">
                            <h5 class="mb-3" style="color: #007bff; font-size: 1.2em;">修改关系</h5>
                            <div id="relationship-list" style="display: flex; flex-direction: column;"></div>

                            <div style="display: flex; align-items: center; margin-top: 10px;">
                                <div class="form-group" style="flex: 1; margin-right: 5px;">
                                    <label for="new-relationship-direction">方向:</label>
                                    <select id="new-relationship-direction" class="form-select"
                                        style="font-size: 0.9em;">
                                        <option value="from_new_to_target">-&gt;</option>
                                        <option value="from_target_to_new">&lt;-</option>
                                    </select>
                                </div>

                                <div class="form-group" style="flex: 2; margin-right: 5px;">
                                    <label for="new-relationship-type">关系类型:</label>
                                    <input type="text" id="new-relationship-type" class="form-control"
                                        oninput="searchRelationshipTypes(this.value)" placeholder="输入关系类型"
                                        style="font-size: 0.9em;">
                                    <div id="relationship-type-suggestions" class="suggestions"></div>
                                </div>

                                <div class="form-group" style="flex: 2; margin-right: 5px;">
                                    <label for="new-target-node">与被选节点连接的节点:</label>
                                    <input type="text" id="new-target-node" class="form-control"
                                        oninput="searchNodes(this.value)" placeholder="输入目标节点"
                                        style="font-size: 0.9em;">
                                    <div id="node-suggestions" class="suggestions"></div>
                                </div>

                                <button type="button" class="btn btn-outline-primary" onclick="addRelationship()"
                                    style="font-size: 0.9em;">添加关系</button>
                            </div>
                        </div>

                        <!-- 提交按钮 -->
                        <div class="text-center mt-4" style="grid-column: span 3;">
                            <button type="submit" class="btn btn-primary" style="font-size: 1em;">提交修改</button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</body>
<script>
    let network;
    let allNodes = {};
    let activeNodes = {};
    let nodeGroups = {};
    let hiddenGroups = new Set();
    let expandedNodes = {};
    let lastClickedNode = null;
    let originalNodeTypes = [];
    let currentScale = 100;

    let relationships = []; // 用于存储关系信息
    let origin_relationships = []; // 存储原始关系

    async function loadRelationships() {
        const nodeId = document.getElementById('node-id').innerText; // 获取当前节点的 ID
        const response = await fetch(`/get_related_nodes`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ nodeId: nodeId })
        });

        if (response.ok) {
            const data = await response.json();
            origin_relationships = data.related_nodes;
            relationships = Object.assign([], origin_relationships);
            displayExistingRelationships(relationships);
        } else {
            console.error('Failed to load relationships:', response);
        }
    }

    function displayExistingRelationships(relationships) {
        const relationshipList = document.getElementById('relationship-list');
        relationshipList.innerHTML = ''; // 清空现有内容

        relationships.forEach((relationship) => {
            const relationshipRow = document.createElement('div');
            relationshipRow.className = 'relationship-row';
            relationshipRow.style.display = 'flex';
            relationshipRow.style.alignItems = 'center';
            relationshipRow.style.marginBottom = '5px';

            // 创建方向选择框
            const directionSelect = document.createElement('select');
            directionSelect.className = 'form-select';
            directionSelect.style.width = '70px';
            directionSelect.innerHTML = `<option value="from_new_to_target" ${(relationship.direction == 'from_new_to_target') ? 'selected' : ''}>-&gt;</option>
            <option value="from_target_to_new" ${(relationship.direction == 'from_target_to_new') ? 'selected' : ''}>&lt;-</option>`;

            // 创建类型输入框
            const typeInput = document.createElement('input');
            typeInput.className = 'form-input';
            typeInput.style.flex = '1';
            typeInput.placeholder = '关系类型';
            typeInput.value = relationship.relationship;

            // 创建目标节点输入框
            const targetNodeInput = document.createElement('input');
            targetNodeInput.className = 'form-input';
            targetNodeInput.style.flex = '1';
            targetNodeInput.placeholder = '目标节点';
            targetNodeInput.value = relationship.node;

            // 创建删除关系按钮
            const deleteButton = document.createElement('button');
            deleteButton.innerText = '删除关系';
            deleteButton.style.marginLeft = '5px';
            deleteButton.onclick = function () {
                handleDeleteRelationship(relationshipRow, relationship); // 传入要删除的行和关系对象
            };
            // 组合到行中
            relationshipRow.appendChild(directionSelect);
            relationshipRow.appendChild(typeInput);
            relationshipRow.appendChild(targetNodeInput);
            relationshipRow.appendChild(deleteButton);

            relationshipList.appendChild(relationshipRow);
        });
    }

    function handleDeleteRelationship(relationshipRow, relationship) {
        // 从当前的关系数组中删除对应的关系
        console.log('Deleting relationship:', relationship);
        // 使用 filter 方法进行删除，保持其他关系
        relationships = relationships.filter(rel => rel != relationship);
        // 更新 DOM，从当前显示的列表中移除该行
        relationshipRow.remove();
    }


    function addRelationship() {
        const direction = document.getElementById('new-relationship-direction').value;
        const relationshipType = document.getElementById('new-relationship-type').value;
        const targetNode = document.getElementById('new-target-node').value;

        relationships.push({
            direction:direction,
            relationship: relationshipType,
            node: targetNode
        }); // 新关系加入到relationships中
        displayExistingRelationships(relationships); // 更新显示
    }

    async function searchRelationshipTypes(keyword) {
        const response = await fetch(`/search_relationship_types?keyword=${keyword}`);
        const suggestions = await response.json();
        // Display suggestions in the relationship type input section
        const suggestionsDiv = document.getElementById('relationship-type-suggestions');
        suggestionsDiv.innerHTML = '';
        suggestions.forEach(suggestion => {
            const suggestionItem = document.createElement('div');
            suggestionItem.textContent = suggestion;
            suggestionItem.onclick = () => {
                document.getElementById('new-relationship-type').value = suggestion;
                suggestionsDiv.innerHTML = ''; // Clear suggestions
            };
            suggestionsDiv.appendChild(suggestionItem);
        });
    }

    async function searchNodes(keyword) {
        const response = await fetch(`/search_nodes?name=${keyword}`);
        const suggestions = await response.json();
        // Display suggestions in the node input section
        const suggestionsDiv = document.getElementById('node-suggestions');
        suggestionsDiv.innerHTML = '';
        suggestions.forEach(suggestion => {
            const suggestionItem = document.createElement('div');
            suggestionItem.textContent = suggestion.name; // Assume node has a 'name' property
            suggestionItem.onclick = () => {
                document.getElementById('new-target-node').value = suggestion.name;
                suggestionsDiv.innerHTML = ''; // Clear suggestions
            };
            suggestionsDiv.appendChild(suggestionItem);
        });
    }

    function increaseScale() {
        currentScale += 10;
        if (currentScale > 200) currentScale = 200;
        applyScale();
    }

    function decreaseScale() {
        currentScale -= 10;
        if (currentScale < 50) currentScale = 50;
        applyScale();
    }

    function applyScale() {
        document.getElementById('node-info').style.transform = `scale(${currentScale / 100})`;
    }

    //删除节点
    async function deleteNodeById(nodeId) {
        try {
            // 发送删除请求到后端
            const response = await fetch('/delete_node', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ nodeId: nodeId })
            });

            // 处理响应
            if (response.ok) {
                const result = await response.json();
                alert(result.message);
                window.location.href = "/knowledge_admin";
            } else {
                alert('Error deleting node.');
            }
        } catch (error) {
            alert('Error: ' + error);
        }
    }

    //删除
    // 删除节点并显示相关节点信息
    async function delNodeInfo() {
        const nodeName = document.getElementById('node-name').textContent; // 获取当前选中节点的名称
        const nodeId = document.getElementById('node-id').textContent; // 获取当前选中节点的编号

        try {
            // 获取与节点相关的其他节点及关系
            const response = await fetch('/get_related_nodes', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ nodeId: nodeId })
            });

            if (response.ok) {
                const result = await response.json();

                // 显示弹窗内容
                const relatedNodes = result.related_nodes;

                let message = `确定删除节点 "${nodeName}" 以及以下关联关系吗？\n\n`;

                relatedNodes.forEach(node => {
                    const direction = node.direction === 'outgoing' ? '指向' : '被指向';
                    message += `节点 "${node.node}" (${direction} - ${node.relationship})\n`;
                });

                if (relatedNodes.length === 0) {
                    message += "该节点没有与其他节点的关联关系。\n";
                }

                const userConfirmed = confirm(message);

                if (userConfirmed) {
                    deleteNodeById(nodeId); // 调用删除函数
                }
            } else {
                alert('Error fetching related nodes.');
            }
        } catch (error) {
            alert('Error: ' + error);
        }
    }

    //搜索节点
    function searchNodes() {
        const targetName = document.getElementById('targetName').value;
        if (!targetName) {
            document.getElementById('searchResults').innerHTML = '';
            return;
        }

        fetch(`/search_nodes?name=${encodeURIComponent(targetName)}`)
            .then(response => response.json())
            .then(data => {
                const searchResults = document.getElementById('searchResults');
                searchResults.innerHTML = '';

                if (Array.isArray(data)) {
                    data.forEach(node => {
                        const link = document.createElement('a');
                        link.href = '#';
                        link.textContent = node.name;
                        link.onclick = function () {
                            document.getElementById('targetName').value = node.name;
                            searchResults.innerHTML = '';
                        };
                        searchResults.appendChild(link);
                    });
                } else {
                    console.error('Invalid data format:', data);
                }
            })
            .catch(error => {
                console.error('Error:', error);
            });
    }

    document.getElementById('nodeForm').addEventListener('submit', function (event) {
        event.preventDefault();

        const formData = new FormData();
        formData.append('label', document.getElementById('label').value);
        formData.append('name', document.getElementById('name1').value);
        formData.append('description', document.getElementById('description').value);
        formData.append('types', document.getElementById('label').value);
        formData.append('target_name', document.getElementById('targetName').value);
        formData.append('relationship_type', document.getElementById('relationshipType').value);
        formData.append('relationship_direction', document.getElementById('relationshipDirection').value);

        fetch('/add_node_with_relationship', {
            method: 'POST',
            body: formData
        })
            .then(response => response.json())
            .then(data => {
                console.log('Response:', data);
                if (data.error) {
                    alert(data.error);
                } else {
                    alert('节点添加成功');
                    window.location.href = '/knowledge_admin';
                }
            })
            .catch(error => {
                console.error('Error:', error);
                alert('节点添加失败');
            });
    });


    function checkLoginAndRedirect(destination) {
        fetch('/check_login_status')
            .then(response => response.json())
            .then(data => {
                if (!data.logged_in) {
                    alert("请先登录！");
                } else {
                    if (destination == '/knowledge') {
                        if (data.userRole == 'admin') {
                            window.location.href = '/knowledge_admin';
                        } else {
                            window.location.href = '/knowledge';
                        }
                    } else {
                        window.location.href = destination;
                    }

                }
            })
            .catch(error => {
                console.error('检查登录状态时发生错误:', error);
            });
    }

    document.addEventListener('DOMContentLoaded', function () {
        fetchDefaultGraph();
    });

    async function fetchDefaultGraph() {
        const response = await fetch('/default-graph');
        if (!response.ok) {
            alert("无法加载默认图形数据，请重试");
            return;
        }
        const data = await response.json();
        const max_node_name_len = 10
        const nodes = data.nodes.map(node => ({
            id: node.id,
            label: node.properties.name.length > max_node_name_len ? node.properties.name.slice(0, max_node_name_len) + '...' : node.properties.name,
            fullName: node.properties.name,
            description: node.properties.description || "暂无简介",  // 简介字段
            group: node.types.join(', '),
            shape: 'circle',
            fixed: {
                x: false,
                y: false
            },
            font: {
                size: 10,
                color: '#ffffff',
                align: 'center',
                bold: true,
                strokeWidth: 2,
                strokeColor: '#000000'
            }
        }));

        const edges = data.relationships.map(rel => ({
            from: rel.start,
            to: rel.end,
            label: rel.type,
            arrows: 'to',
            font: {
                size: 8,
                align: 'horizontal'
            }
        }));

        allNodes = nodes.reduce((acc, node) => {
            acc[node.id] = node;
            return acc;
        }, {});

        activeNodes = {
            ...allNodes
        };

        nodeGroups = [...new Set(nodes.flatMap(node => node.group.split(', ')))];
        //默认展示妊娠心脏病
        // expandNode(nodes[0].id);
        drawGraph(nodes, edges);
        createLegend();
    }

    async function queryGraph() {
        hideExpandIcon();

        const name = document.getElementById('name').value;
        if (!name) {
            alert("请输入实体名称");
            return;
        }
        const response = await fetch(`/query?name=${name}`);
        if (!response.ok) {
            alert("查询失败，请重试");
            return;
        }
        const data = await response.json();
        const max_node_name_len = 10
        const nodes = data.nodes.map(node => ({
            id: node.id,
            label: node.properties.name.length > max_node_name_len ? node.properties.name.slice(0, max_node_name_len) + '...' : node.properties.name,
            fullName: node.properties.name,
            description: node.properties.description || "暂无简介",  // 简介字段
            group: node.types.join(', '),
            shape: 'circle',
            fixed: {
                x: false,
                y: false
            },
            font: {
                size: 10,
                color: '#ffffff',
                align: 'center',
                strokeWidth: 2,
                strokeColor: '#000000'
            }
        }));

        const edges = data.relationships.map(rel => ({
            from: rel.start,
            to: rel.end,
            label: rel.type,
            arrows: 'to',
            font: {
                size: 8,
                align: 'horizontal'
            }
        }));

        allNodes = nodes.reduce((acc, node) => {
            acc[node.id] = node;
            return acc;
        }, {});

        activeNodes = {
            ...allNodes
        };

        nodeGroups = [...new Set(nodes.flatMap(node => node.group.split(', ')))];

        drawGraph(nodes, edges);
        createLegend();
        // nodes.forEach(function (node) {
        //     expandNode(node.id)
        // });
    }

    function drawGraph(nodes, edges) {
        const container = document.getElementById('graph');
        const data = {
            nodes: new vis.DataSet(nodes),
            edges: new vis.DataSet(edges)
        };
        const options = {
            nodes: {
                shape: 'circle',
                size: 30,
                font: {
                    size: 10,
                    color: '#ffffff',
                    face: 'Microsoft YaHei, PingFang SC, Noto Sans SC, sans-serif',
                    strokeWidth: 2,
                    strokeColor: '#000000'
                },
                borderWidth: 2,
                borderWidthSelected: 3,
            },
            edges: {
                width: 1,
                color: {
                    color: '#888888',
                    highlight: '#888888',
                    hover: '#888888'
                },
                smooth: {
                    type: 'continuous'
                },
                arrows: {
                    to: {
                        enabled: true,
                        scaleFactor: 0.8,
                        type: 'arrow'
                    }
                },
                font: {
                    size: 13,
                    face: 'Microsoft YaHei, PingFang SC, Noto Sans SC, sans-serif',
                    align: 'middle'
                }
            },
            physics: {
                stabilization: true,
                forceAtlas2Based: {
                    gravitationalConstant: -10,
                    centralGravity: 0.001,
                    springLength: 128,
                    springConstant: 0.008,
                    damping: 2.5,
                    avoidOverlap: 3.5
                },
                solver: 'forceAtlas2Based'
            },
            interaction: {
                tooltipDelay: 0,
                hover: true
            }
        };
        network = new vis.Network(container, data, options);

        network.on("click", function (params) {
            if (params.nodes.length > 0) {
                const nodeId = params.nodes[0];
                const node = allNodes[nodeId];
                if (lastClickedNode === nodeId) {
                    hideExpandIcon();
                    lastClickedNode = null;
                } else {
                    displayNodeInfo(node);
                    showExpandIcon(nodeId, params.pointer.DOM);
                    lastClickedNode = nodeId;
                }
            } else {
                hideExpandIcon();
            }
        });

        network.on("dragEnd", function (params) {
            hideExpandIcon();
        });

        network.on("zoom", function (params) {
            hideExpandIcon();
        });
    }

    function createLegend() {
        const legend = document.getElementById('legend');
        legend.innerHTML = '';

        nodeGroups.forEach((group, index) => {
            const nodeId = Object.keys(network.body.nodes).find(id => allNodes[id].group.includes(group));
            const color = network.body.nodes[nodeId].options.color.background;

            const legendItem = document.createElement('div');
            legendItem.className = 'legend-item';
            legendItem.onclick = () => toggleCategory(group);

            const legendColor = document.createElement('div');
            legendColor.className = 'legend-color';
            legendColor.style.backgroundColor = color;

            const legendText = document.createElement('span');
            legendText.innerText = group;

            legendItem.appendChild(legendColor);
            legendItem.appendChild(legendText);

            legend.appendChild(legendItem);
        });
    }

    function toggleCategory(category) {
        const nodesToToggle = Object.values(allNodes).filter(node => node.group.includes(category));
        const currentNodeIds = new Set(network.body.data.nodes.getIds());

        if (hiddenGroups.has(category)) {
            nodesToToggle.forEach(node => {
                if (!currentNodeIds.has(node.id)) {
                    network.body.data.nodes.add(node);
                }
            });
            hiddenGroups.delete(category);
        } else {
            nodesToToggle.forEach(node => {
                if (currentNodeIds.has(node.id)) {
                    network.body.data.nodes.remove(node.id);
                }
            });
            hiddenGroups.add(category);
        }
    }

    function updateLegend() {
        const currentGroups = [...new Set(Object.values(allNodes).flatMap(node => node.group.split(', ')))];
        nodeGroups = currentGroups;
        createLegend();
    }

    function displayNodeInfo(node) {
        const nodeInfoDiv = document.getElementById('node-info');
        document.getElementById('node-id').innerText = node.id;
        document.getElementById('node-name').innerText = node.fullName;
        document.getElementById('node-group').innerText = node.group;
        document.getElementById('node-description').innerText = node.description;  // 新增展示简介部分
        nodeInfoDiv.style.display = 'block';
    }

    async function showExamplePatients(s_name = '') {
        const nodeId = lastClickedNode;  // 使用最近点击的节点ID
        const node = allNodes[nodeId];  // 获取节点信息
        const search_name = ((s_name == '') ? node.fullName : s_name); // 用来存储sql首页出院病历模糊搜索的疾病
        const flag = ((s_name == '') ? 0 : 1)
        const response = await fetch(`/patient?search_name=${search_name}&flag=${flag}`);
        if (!response.ok) {
            alert("未找到相关病历");
            return;
        }
        const data = await response.json();  // 获取到的 data 是字典列表\

        const popup = document.createElement('div');
        popup.style.position = 'fixed';
        popup.style.top = '50%';
        popup.style.left = '50%';
        popup.style.transform = 'translate(-50%, -50%)';
        popup.style.backgroundColor = 'white';
        popup.style.border = '2px solid #ccc';
        popup.style.borderRadius = '8px';
        popup.style.padding = '20px';
        popup.style.zIndex = '1000';
        popup.style.width = '80%';
        popup.style.height = '80%';
        popup.style.overflowY = 'scroll';
        popup.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)';

        // 关闭按钮，放在弹出窗口的右上角，始终可见
        const closeButton = document.createElement('span');
        closeButton.innerHTML = '&times;';
        closeButton.style.position = 'sticky';
        closeButton.style.top = '0px';
        closeButton.style.right = '0px';
        closeButton.style.cursor = 'pointer';
        closeButton.style.fontSize = '24px';
        closeButton.style.float = 'right';
        closeButton.onclick = () => document.body.removeChild(popup);

        // 将关闭按钮添加到弹出窗口的顶部
        popup.appendChild(closeButton);

        // 创建表格
        const table = document.createElement('table');
        table.className = 'table table-bordered table-striped';
        const header = table.createTHead();
        const headerRow = header.insertRow(0);
        const headers = data.shown_headers;

        headers.forEach(text => {
            const cell = document.createElement('th');
            cell.innerText = text;
            headerRow.appendChild(cell);
        });

        const body = table.createTBody();

        data.patients.forEach(row => {
            const tableRow = body.insertRow();
            headers.slice(0, -1).forEach(header => {
                const cell = tableRow.insertCell();
                cell.innerText = row[header];
            });

            // 创建“详情”按钮
            const detailCell = tableRow.insertCell();
            const detailButton = document.createElement('button');
            detailButton.className = 'btn btn-primary';
            detailButton.innerText = '详情';
            detailButton.onclick = () => showPatientDetails(row, data.order_headers);
            detailCell.appendChild(detailButton);
        });

        popup.appendChild(table);

        document.body.appendChild(popup);
    }

    function showPatientDetails(patientData, order_headers) {
        const detailPopup = document.createElement('div');
        detailPopup.style.position = 'fixed';
        detailPopup.style.top = '50%';
        detailPopup.style.left = '50%';
        detailPopup.style.transform = 'translate(-50%, -50%)';
        detailPopup.style.backgroundColor = 'white';
        detailPopup.style.border = '2px solid #ccc';
        detailPopup.style.borderRadius = '8px';
        detailPopup.style.padding = '20px';
        detailPopup.style.zIndex = '1000';
        detailPopup.style.width = '50%';
        detailPopup.style.height = '50%';
        detailPopup.style.overflowY = 'scroll';
        detailPopup.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)';

        // 关闭按钮，放在弹出窗口的右上角，始终可见
        const closeButton = document.createElement('span');
        closeButton.innerHTML = '&times;';
        closeButton.style.position = 'sticky';
        closeButton.style.top = '0px';
        closeButton.style.right = '0px';
        closeButton.style.cursor = 'pointer';
        closeButton.style.fontSize = '24px';
        closeButton.style.float = 'right';
        closeButton.onclick = () => document.body.removeChild(detailPopup);

        // 将关闭按钮添加到弹出窗口的顶部
        detailPopup.appendChild(closeButton);

        // 创建表格
        const table = document.createElement('table');
        table.className = 'table table-bordered';
        order_headers.forEach(order_header => {
            const row = table.insertRow();
            const cell1 = row.insertCell(0);
            cell1.innerText = order_header;

            const cell2 = row.insertCell(1);
            cell2.innerText = patientData[order_header];
        });

        detailPopup.appendChild(table);

        document.body.appendChild(detailPopup);
    }

    function toggleNodeInfo() {
        const nodeInfoDiv = document.getElementById('node-info');
        if (nodeInfoDiv.style.display === 'block') {
            nodeInfoDiv.style.display = 'none';
        } else {
            nodeInfoDiv.style.display = 'block';
        }
    }

    function showExpandIcon(nodeId, position) {
        const expandIcon = document.getElementById('expand-icon');
        expandIcon.style.left = (position.x + 10) + 'px';
        expandIcon.style.top = (position.y - 10) + 'px';
        expandIcon.style.display = 'block';
        expandIcon.onclick = () => toggleExpandNode(nodeId);
    }

    function hideExpandIcon() {
        const expandIcon = document.getElementById('expand-icon');
        expandIcon.style.display = 'none';
    }

    async function toggleExpandNode(nodeId) {
        if (expandedNodes[nodeId]) {
            collapseNode(nodeId);
            hideExpandIcon();
        } else {
            await expandNode(nodeId);
            hideExpandIcon();
        }
    }

    async function expandNode(nodeId) {
        const response = await fetch(`/expand?id=${nodeId}`);
        if (!response.ok) {
            alert("扩展节点失败，请重试");
            return;
        }
        const data = await response.json();

        expandedNodes[nodeId] = {
            nodes: [],
            edges: []
        };
        const max_node_name_len = 10
        data.nodes.forEach(node => {
            if (!allNodes[node.id]) {
                allNodes[node.id] = {
                    id: node.id,
                    label: node.properties.name.length > max_node_name_len ? node.properties.name.slice(0, max_node_name_len) + '...' : node.properties.name,
                    fullName: node.properties.name,
                    description: node.properties.description || "暂无简介",  // 简介字段
                    group: node.types.join(', '),
                    shape: 'circle',
                    fixed: {
                        x: false,
                        y: false
                    },
                    font: {
                        size: 10,
                        color: '#ffffff',
                        align: 'center',
                        strokeWidth: 2,
                        strokeColor: '#000000'
                    }
                };
                network.body.data.nodes.add(allNodes[node.id]);
                expandedNodes[nodeId].nodes.push(node.id);
            }
        });

        data.relationships.forEach(rel => {
            network.body.data.edges.add({
                from: rel.start,
                to: rel.end,
                label: rel.type,
                arrows: 'to',
                font: {
                    size: 8,
                    align: 'horizontal'
                }
            });

            expandedNodes[nodeId].edges.push(rel.id);
        });

        expandedNodes[nodeId].expanded = true;
        updateLegend();
    }

    function collapseNode(nodeId) {
        const nodesToRemove = expandedNodes[nodeId].nodes;
        const edgesToRemove = expandedNodes[nodeId].edges;

        nodesToRemove.forEach(id => {
            network.body.data.nodes.remove(id);
            delete allNodes[id];
        });

        edgesToRemove.forEach(edgeId => {
            network.body.data.edges.remove(edgeId);
        });

        delete expandedNodes[nodeId];
        updateLegend();
    }

    function showEditModal() {
        const nodeName = document.getElementById('node-name').innerText;
        const nodeDescription = document.getElementById('node-description').innerText;
        const nodeTypes = document.getElementById('node-group').innerText.split(", ");

        originalNodeTypes = [...nodeTypes];  // 记录原始类别

        document.getElementById('edit-node-name').value = nodeName;
        document.getElementById('edit-node-description').value = nodeDescription;

        const typesContainer = document.getElementById('edit-node-types');
        typesContainer.innerHTML = '';
        console.log(nodeTypes);
        if (nodeTypes[0] != "") {
            nodeTypes.forEach(type => {
                const div = document.createElement('div');
                div.innerHTML = `${type} <button type="button" onclick="removeNodeType(this, '${type.replace(/\n/g, '')}')">移除</button>`;
                typesContainer.appendChild(div);
            })
        }
        loadRelationships();
        const editModal = new bootstrap.Modal(document.getElementById('editModal'));
        editModal.show();
    }

    function addNodeType() {
        const newType = document.getElementById('new-type-select').value;
        if (!newType) return;

        const typesContainer = document.getElementById('edit-node-types');
        const existingTypes = Array.from(typesContainer.children).map(div => div.innerText.trim().split(' ')[0]);
        if (existingTypes.includes(newType)) {
            alert("该类别已经存在");
            return;
        }

        const div = document.createElement('div');
        div.innerHTML = `${newType} <button type="button" onclick="removeNodeType(this, '${newType.replace(/\n/g, '')}')">移除</button>`;
        typesContainer.appendChild(div);
    }

    function removeNodeType(button, type) {
        button.parentElement.remove();
    }

    document.getElementById('editNodeForm').addEventListener('submit', function (event) {
        event.preventDefault();

        const nodeId = document.getElementById('node-id').innerText;
        const newName = document.getElementById('edit-node-name').value;
        const newDescription = document.getElementById('edit-node-description').value;
        // 收集节点类别，这里可以使用原有逻辑
        const updatedNodeTypes = Array.from(document.getElementById('edit-node-types').children)
            .map(div => div.innerText.trim().split(' ')[0]);

        const addNodeTypes = updatedNodeTypes.filter(type => !originalNodeTypes.includes(type));  // 新增类别
        const removeNodeTypes = originalNodeTypes.filter(type => !updatedNodeTypes.includes(type));  // 删除类别

        const addRelationships = relationships.filter(rel => !origin_relationships.includes(rel));
        const removeRelationships = origin_relationships.filter(orig => !relationships.includes(orig));
        // 通过POST将所有修改的数据一起发送到后端
        fetch('/update_node', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                identity: parseInt(nodeId),
                name: newName,
                description: newDescription,
                add_node_types: addNodeTypes,
                remove_node_types: removeNodeTypes,
                add_relationships: addRelationships, // 新增的关系
                remove_relationships: removeRelationships // 删除的关系
            })
        })
            .then(response => response.json())
            .then(data => {
                if (data.status === 'success') {
                    alert('节点修改成功');
                    location.reload();
                } else {
                    alert('节点修改失败');
                }
            })
            .catch(error => {
                console.error('Error:', error);
                alert('请求失败');
            });
    });
    function logout() {
        fetch('/logout')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    window.location.href = '/';
                } else {
                    alert(data.error);
                }
            });
    }
</script>
</body>

</html>